<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/5/9
 * Time: 23:08
 */

namespace corephp;


use corephp\base\Autoload;
use corephp\base\Config;
use corephp\base\Factory;
use corephp\exception\Exception;
use corephp\exception\NotFoundException;
use corephp\log\File;
use corephp\middleware\Middleware;
use corephp\route\Route;
use corephp\view\CoreView;

/**
 * Class App
 * @package corephp
 * @method \corephp\exception\Exception exception()
 * @method \corephp\log\LogAbstract logger()
 * @method \corephp\route\Route route()
 * @method \corephp\view\Template view()
 */
class App
{


    public static function run($config)
    {
        define('COREPHP_PATH',__DIR__);
        require __DIR__ . '/base/Autoload.php';

        //自动载入
        $loadDir = isset($config['autoload_path']) ? array_merge([
            dirname(__DIR__)
        ], $config['autoload_path']) : [dirname(__DIR__)];

        new Autoload($loadDir);
        //配置初始化
        $packages = isset($config['packages']) ? array_merge(self::_packages(),$config['packages']) : self::_packages();
        $config['packages'] = $packages;
        self::config()->init($config);
        //异常处理
        self::exception()->logger = self::logger();
        self::exception()->debug = self::config()->get('debug');
        self::exception()->register();
        //执行主体
        self::_excute();

    }

    /**
     * 默认处理
     * @return array
     */
    private static function _packages()
    {
        return [
            //中间件管理
            'middleware'=>[
                'class'=>Middleware::class
            ],
            //日志处理
            'logger'       => [
                'class' => File::class,
                'property'=>[
                    'logPath'=> getcwd().'/runtime/logs'
                ]
            ],
            //异常处理
            'exception' => [
                'class' => Exception::class,
            ],
            //模板配置
            'view'      => [
                'class' => CoreView::class
            ],
            //路由
            'route'     => [
                'class' => Route::class,
                'defaultRoute'=>self::config()->get('defaultRoute')
            ],
            //数据库
            'db'=>[
                'class'=>\corephp\db\connect\Medoo::class,
                'param'=>[

                    [
                        // required
                        'database_type' => 'mysql',
                        'database_name' => 'chapiaoling',
                        'server'        => 'localhost',
                        'username'      => 'root',
                        'password'      => '',

                        // [optional]
                        'charset'       => 'utf8',
                        'port'          => 3306,

                        // [optional] Table prefix
                        'prefix'        => 'cp_',

                        // [optional] Enable logging (Logging is disabled by default for better performance)
                        'logging'       => true,


                        // [optional] driver_option for connection, read more from http://www.php.net/manual/en/pdo.setattribute.php
                        'option'        => [
                            \PDO::ATTR_CASE => \PDO::CASE_NATURAL
                        ],

                        // [optional] Medoo will execute those commands after connected to the database for initialization
                        'command'       => [
                            'SET SQL_MODE=ANSI_QUOTES'
                        ]
                    ]
                ]
            ]
        ];
    }
    /**
     * 执行主体
     * @throws NotFoundException
     */
    private static function _excute()
    {
        //路由处理
        $route = self::route()->parse();
        $className = preg_replace('/\\+|\/+/', '\\', self::config()->get('controllerNamespace') . '/' . $route['class']).'Controller';
        if(!class_exists($className)){
            throw new NotFoundException('未找到'.$className);
        }
        $controller = new $className;
        if(!is_callable([$controller,$route['action']],true, $callableName)){
            throw new NotFoundException($callableName.'不存在或不是public属性');
        }
        //中间件
        if(isset($config['middleware'])){
            $middleWare = new Middleware($config['middleware']);
            $middleWare->beforeRun();
            echo call_user_func_array([$controller,$route['action']],$route['arguments']);
            $middleWare->afterRun();
        }else{
            echo call_user_func_array([$controller,$route['action']],$route['arguments']);
        }
    }

    /**
     * @return Config
     */
    public static function config()
    {
        return self::singleObject([
            'class' => Config::class
        ]);
    }
    /**
     * 单例模式创建实例
     * @param $name
     * @param $arguments
     * @return mixed|null
     */
    public static function __callStatic($name, $arguments)
    {
        $packages = self::config()->get('packages');
        if (isset($packages[$name])) {
            return self::singleObject($packages[$name]);
        }
        return null;
    }
    /**
     * 创建实例
     * $params = [
     *     'class'=>要实例化的类名,
     *     'property'=>对象的属性,
     *     'param'=>构造函数需要的参数
     * ]
     * @param $params
     * @return object
     */
    public static function createObject($params)
    {
        return Factory::createObject($params);
    }
    /**
     * 单例模式实例化
     * @param $params
     * @return object
     * @see Container
     */
    public static function singleObject($params)
    {
        return Factory::singleObject($params);
    }
    /**
     * 单例模式取得容器实例
     * @return \corephp\base\Container
     */
    public static function container()
    {
        return Factory::container();
    }
}